
from os import path
from rs485tomqtt.device import Device
from .modbus import ModbusComm
from ..mqtt_client import MqttClient
from .meter645com import Meter645Client
from json import loads
from queue import Queue


# 串口服务器
class CommHandler:
    def __init__(self, tag: str, commConfig: dict, mqttClient: MqttClient, filePath: str):
        self._hd = None
        self.filePath = filePath
        self.mqttClient = mqttClient
        self.commConfig = commConfig
        # 订阅主题列表
        self.rpcTopicList = []
        # 串口服务器下设备列表 key是唯一名，value是Device设备类型
        self.deviceDic: dict[str, Device] = {}
        self.loadDevices()
        self.mqttClient.addTopicList(self.rpcTopicList)

        if tag == "modbus_slaves":
            self._hd = ModbusComm(commConfig, mqttClient, self.deviceDic)
        elif tag == "proto_645":
            self._hd = Meter645Client(commConfig, mqttClient, self.deviceDic)
        # elif tag == TAG_CJT188:
        #     self._hd = ProtoCjt188Comm(conf)
        # elif tag == TAG_MONITOR:
        #     self._hd = Monitor(conf)
        # else:
        #     raise NotImplementedError()

    def loadDevices(self):
        for deviceItem in self.commConfig["devices"]:
            dev_type = deviceItem.get("type")
            config_file = (self.filePath + "config/devicesType/"
                           + dev_type).replace('/', path.sep) + ".json"
            try:
                with open(config_file, encoding="utf-8") as dev_p_conf:
                    conf: dict = loads(dev_p_conf.read())
            finally:
                # 确保文件在操作后关闭
                dev_p_conf.close()
            if conf["rpcTopic"] not in self.rpcTopicList:
                self.rpcTopicList.append(conf["rpcTopic"])
            rpcDic = {}
            for item in conf["rpc"]:
                rpcDic[item["key"]] = item
            deviceConfig = {
                "addr": deviceItem["addr"],
                "name": deviceItem["name"],
                "type": conf["type"],
                "host": self.commConfig["host"],
                "port": self.commConfig["port"],
                "topic": conf["topic"],
                "rpctopic": conf["rpcTopic"],
                "ts": conf["ts"],
                "rpc":  rpcDic,
                "byteOrder": conf.get("byteOrder"),
                "wordOrder": conf.get("wordOrder")
            }
            device = Device(deviceConfig)
            self.deviceDic[deviceItem["name"]] = device

    async def run_async_client(self):
        await self._hd.run_async_client()
